package com.eascs.admin.o2o.badloan.service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.eascs.admin.common.vo.ModelResult;
import com.eascs.admin.o2o.badloan.dao.O2oCancleDao;
import com.eascs.admin.o2o.badloan.entity.O2oCacleEntity;
import com.eascs.admin.o2o.badloan.entity.O2oCacleForm;
import com.eascs.admin.o2o.badloan.form.O2oCacleTForm;
import com.eascs.admin.o2o.finance.entity.O2oFinanceFlowEntity;
import com.eascs.admin.o2o.finance.service.O2oFinanceFlowService;
import com.eascs.admin.o2o.internal.dao.WfTypeStatusDao;
import com.eascs.admin.o2o.internal.entity.WfTypeStatus;
import com.eascs.admin.o2o.internal.entity.LoanapplyExpand;
import com.eascs.admin.o2o.internal.service.LoanapplyExpandService;
import com.eascs.admin.o2o.internal.util.StatusContexts;
import com.eascs.admin.o2o.loan.entity.O2oLoanapplyEntity;
import com.eascs.admin.o2o.loan.service.O2oChargeSituationService;
import com.eascs.admin.o2o.loan.service.O2oLoanapplyService;
import com.eascs.admin.o2o.o2ozx.serviceimpl.O2oZxServiceImpl;
import com.eascs.admin.o2o.zx.entity.O2oZxEntity;
import com.eascs.admin.recordlog.constant.O2oLogType;
import com.eascs.admin.recordlog.servcie.O2oRecordLogService;
import com.eascs.app.dao.PageResult;
import com.eascs.app.log.Logger;
import com.eascs.app.log.LoggerFactory;
import com.eascs.common.util.StringUtil;
import com.eascs.common.util.UuidUtil;
import com.eascs.web.sso.User;
import com.eascs.web.sso.UserHolder;
import com.eascs.workflow.common.entity.wf.ProcessTemplate;
import com.eascs.workflow.common.service.wf.WorkFlowService;
import com.eascs.workflow.common.vo.CancleProcessParam;
import com.fasterxml.jackson.databind.ObjectMapper;

@Service
public class O2oCancleServiceImpl implements ICancelService {

	private static Logger logger = LoggerFactory.getLogger(O2oCancleServiceImpl.class);

	@Autowired
	O2oCancleDao cancleDao;
	@Autowired
	private O2oFinanceFlowService o2oFinanceFlowService;
	@Autowired
	private O2oLoanapplyService o2oLoanapplyService;
	@Reference
	private WorkFlowService workFlowService;
	@Autowired
	private O2oRecordLogService o2oRecordLogService;
	@Autowired
	private WfTypeStatusDao wfTypeStatusDao;
	@Autowired
	private O2oChargeSituationService o2oChargeSituationService;
	@Autowired
	private LoanapplyExpandService loanapplyExpandService;

	public int insertCalcle(O2oCacleEntity cacleEntity) {
		return cancleDao.insert(cacleEntity);
	}

	public int updateCalcle(O2oCacleEntity cacleEntity) {
		return cancleDao.updateById(cacleEntity);
	}

	public O2oCacleEntity findByIdEntity(String id) {
		return cancleDao.getById(O2oCacleEntity.class, id);
	}

	public O2oCacleEntity findByLoanapplyId(String loanapplyId) {
		return cancleDao.findByLoanapplyId(loanapplyId);
	}

	public O2oCacleTForm findByLoanapplyTId(String loanapplyId) {
		return cancleDao.findByLoanapplyTId(loanapplyId);
	}

	public PageResult<Object[]> findCancelLoanByPage(O2oCacleForm o2oCacleForm) {
		return cancleDao.findCancelLoanByPage(o2oCacleForm);
	}

	public ModelResult<Boolean> worlFlowCancle(O2oCacleEntity payform) {
		ModelResult<Boolean> modelResult = new ModelResult<Boolean>();
		User user = null;
		if (null == UserHolder.getUser()) {
			user = new User();
			user.setNo("1");
			user.setCname("系统管理员");
		} else {
			user = UserHolder.getUser();
		}
		Date date = new Date();
		O2oCacleEntity cacleEntity = findByIdEntity(payform.getId());
		O2oLoanapplyEntity loan = o2oLoanapplyService.findById(payform.getLoanapplyNo());
		LoanapplyExpand expand = loanapplyExpandService.queryLoanapplyNo(payform.getLoanapplyNo());
		if (null == cacleEntity || null == loan) {
			logger.info("cancle workflow fail number:null flow successfully,fail message:cacleEntity is null");
			modelResult.withError("cancle workflow fail", "fail message:cacleEntity is null");
			return modelResult;
		} else if (StatusContexts.O2O_FK_OVER.equals(loan.getWfType())) {
			logger.info("cancle workflow fail number:{} flow successfully,fail message:loanapplyNo is cancled", loan.getLoanapplyNo());
			modelResult.withError("cancle workflow fail", "fail message:loanapplyNo is cancled");
			return modelResult;
		} else if (StatusContexts.O2O_FK_END.equals(loan.getWfType()) || StatusContexts.O2O_REPAY_END.equals(loan.getWfType()) || StatusContexts.O2O_FK_DC.equals(loan.getWfType())) {
			logger.info("cancle workflow fail number:{} flow successfully,fail message:loanapplyNo is loaned or repaymented or compensatored", loan.getLoanapplyNo());
			modelResult.withError("cancle workflow fail", "fail message:loanapplyNo is loaned or repaymented or compensatored");
			return modelResult;
		}
		boolean status = StatusContexts.O2O_NEW.equals(loan.getWfType()) || StatusContexts.O2O_ZX_END.equals(loan.getWfType()) || StatusContexts.O2O_NS_END.equals(loan.getWfType());
		if (null == expand) {
			expand = new LoanapplyExpand();
		}
		if (null == expand.getRedManger()) {
			expand.setRedManger(BigDecimal.ZERO);
		}
		if (null == expand.getRedRisk()) {
			expand.setRedRisk(BigDecimal.ZERO);
		}
		if (null == expand.getRetaManage()) {
			expand.setRetaManage(BigDecimal.ZERO);
		}
		if (null == expand.getRetaRisk()) {
			expand.setRetaRisk(BigDecimal.ZERO);
		}
		BigDecimal redManger = new BigDecimal(0);
		BigDecimal redRisk = new BigDecimal(0);
		redManger = expand.getRedManger().subtract(expand.getRetaManage());
		redRisk = expand.getRedRisk().subtract(expand.getRetaRisk());
		if (redManger.compareTo(BigDecimal.ZERO) > 0 && redRisk.compareTo(BigDecimal.ZERO) > 0) {
			expand.setRedManger(redManger);
			expand.setRedRisk(redRisk);
			if (expand != null && StatusContexts.WFTYPE_STATUS_CLO.equals(expand.getBillStatus())) {
				logger.info("调用退费开始");
				String message = o2oChargeSituationService.Charging(expand, "TF");
				logger.info("调用退费结束，信息：【{}】", message);
			}
		}
		if (status) {
			loan.setWfType(StatusContexts.O2O_FK_OVER);
			loan.setEndDate(date);
			loan.setEndRo(user.getNo());
			O2oLoanapplyEntity loanapply = o2oLoanapplyService.findById(payform.getLoanapplyNo());
			int i = o2oLoanapplyService.updateEntityById(loan);
			saveLog(loanapply, loan, cacleEntity.gettRemark());
			if (i > 0) {
				cacleEntity.settIsSuccess(StatusContexts.O2O_YES);
				updateCalcle(cacleEntity);
				logger.info("cancle fail number:[{}],success", payform.getLoanapplyNo());
				if (StatusContexts.O2O_ZX_END.equals(loanapply.getWfType()) || StatusContexts.O2O_NEW.equals(loanapply.getWfType())) {
					O2oFinanceFlowEntity financeFlowEntity = o2oFinanceFlowService.getByLoanApplyno(payform.getLoanapplyNo());
					if (null != financeFlowEntity && !StatusContexts.O2O_BANK_CLO.equals(financeFlowEntity.getFlowStatus())) {
						if (StatusContexts.O2O_BANK_RUN.equals(financeFlowEntity.getFlowStatus())) {
							CancleProcessParam cancleProcessParam = new CancleProcessParam();
							cancleProcessParam.setReferId(cacleEntity.getLoanapplyNo());
							cancleProcessParam.setOperName(user.getCname());
							cancleProcessParam.setOperNo(user.getNo());
							// 作废财务审核
							cacleEntity.settIsSuccess(StatusContexts.O2O_NO);
							cacleEntity.setId(UuidUtil.generateShortUuid());
							cacleEntity.settType(StatusContexts.WFTYPE_FINANCE);
							cacleEntity.settRemark("征信完成，作废单财务流程未作废，直接作废财务流程");
							cancleProcessParam.setCancleReason(cacleEntity.gettRemark());
							insertCalcle(cacleEntity);
							cancleProcessParam.setProcessType(ProcessTemplate.PROECESS_TYPE_FINANCE_AUDIT);
							cancelProcess(loan, cancleProcessParam, cacleEntity);
						}
						financeFlowEntity.setFlowStatus(StatusContexts.O2O_BANK_CLO);
						o2oFinanceFlowService.update(financeFlowEntity);
					}
				}
				modelResult.withModel(true);
				return modelResult;
			} else {
				logger.info("cancle fail number:[{}],fail message:{{}]", payform.getLoanapplyNo(), "update to o2o_loanapply or insert log fail.");
				modelResult.withError("error", "service cancle error,update to o2o_loanapply or insert log fail.");
				return modelResult;
			}
		} else {
			CancleProcessParam cancleProcessParam = new CancleProcessParam();
			cancleProcessParam.setReferId(cacleEntity.getLoanapplyNo());
			cancleProcessParam.setOperName(user.getCname());
			cancleProcessParam.setOperNo(user.getNo());
			cancleProcessParam.setCancleReason(cacleEntity.gettRemark());
			// 征信准入中
			if (StatusContexts.O2O_ZX_BEGIN.equals(loan.getWfType())) {
				cancleProcessParam.setProcessType("PROCESS_ACCESS");
				ModelResult<Boolean> r = cancelProcess(loan, cancleProcessParam, cacleEntity);
				if (r.isSuccess()) {// 作废成功
					// 作废财务审核
					cacleEntity.settIsSuccess(StatusContexts.O2O_NO);
					cacleEntity.setId(UuidUtil.generateShortUuid());
					cacleEntity.settType(StatusContexts.WFTYPE_FINANCE);
					cacleEntity.settRemark("作废征信，直接作废财务流程");
					insertCalcle(cacleEntity);
					cancleProcessParam.setProcessType(ProcessTemplate.PROECESS_TYPE_FINANCE_AUDIT);
					return cancelProcess(loan, cancleProcessParam, cacleEntity);
				}
				return r;
			}
			// 内审中
			else if (StatusContexts.O2O_NS_BEGIN.equals(loan.getWfType())) {
				ModelResult<Boolean> r = new ModelResult<Boolean>();
				if (StatusContexts.LOAN_TYPE_BK.equals(loan.getLoanType())) {
					cancleProcessParam.setProcessType(ProcessTemplate.PROECESS_TYPE_INAUDIT);
					r = cancelProcess(loan, cancleProcessParam, cacleEntity);
				} else if (StatusContexts.LOAN_TYPE_BP.equals(loan.getLoanType()) || StatusContexts.LOAN_TYPE_BP_JX.equals(loan.getLoanType()) || StatusContexts.LOAN_TYPE_SG.equals(loan.getLoanType()) || StatusContexts.LOAN_TYPE_YC.equals(loan.getLoanType()) || StatusContexts.LOAN_TYPE_SC.equals(loan.getLoanType())) {
					cancleProcessParam.setProcessType(ProcessTemplate.PROECESS_TYPE_INAUDIT_BP);
					r = cancelProcess(loan, cancleProcessParam, cacleEntity);
				}
				return r;
			}
			// 申报中
			else if (StatusContexts.O2O_SB_BEGIN.equals(loan.getWfType())) {
				cancleProcessParam.setProcessType(ProcessTemplate.PROECESS_TYPE_BANK_REPORT);
				ModelResult<Boolean> r = cancelProcess(loan, cancleProcessParam, cacleEntity);
				return r;
			}
		}
		return modelResult;
	}

	/**
	 * @Description: <p>
	 *               作废公共调用workflow接口
	 *               </p>
	 * @author CXW
	 * @date 2017年6月8日 下午2:02:00
	 * @version V1.0
	 */
	public ModelResult<Boolean> cancelProcess(O2oLoanapplyEntity loan, CancleProcessParam cancleProcessParam, O2oCacleEntity cacleEntity) {
		ModelResult<Boolean> modelResult = new ModelResult<Boolean>();
		com.eascs.workflow.common.vo.ModelResult<Boolean> model = workFlowService.cancelProcess(cancleProcessParam);
		if (model.isSuccess()) {
			if (!StatusContexts.WFTYPE_FINANCE.equals(cacleEntity.gettType())) {
				loan.setWfType(StatusContexts.O2O_FK_OVER);
				loan.setEndDate(new Date());
				loan.setEndRo(cancleProcessParam.getOperNo());
				O2oLoanapplyEntity loanapply = o2oLoanapplyService.findById(loan.getLoanapplyNo());
				o2oLoanapplyService.updateEntityById(loan);
				saveLog(loanapply, loan, cacleEntity.gettRemark());
				// updateWfTypeStatus(loan);
			}
			// 更新作废记录表状态
			cacleEntity.settIsSuccess(StatusContexts.O2O_YES);
			updateCalcle(cacleEntity);
			logger.info("cancle workflow success number:{} flow success", loan.getLoanapplyNo());
		} else {
			logger.info("cancle workflow fail number:{} flow successfully,fail message:{}", loan.getLoanapplyNo(), model.getDetailStack());
		}
		modelResult.withModel(model.getModel());
		return modelResult;
	}

	/**
	 * 修改流程主状态表
	 * 
	 * @param loan
	 */
	public void updateWfTypeStatus(O2oLoanapplyEntity loan) {
		// 修改流程主状态表
		WfTypeStatus wfTypeStatus = wfTypeStatusDao.getByLoanapplyNoAndWfType(loan.getLoanapplyNo(), loan.getWfType());
		if (null != wfTypeStatus) {
			wfTypeStatus.setLoapplyNo(loan.getLoanapplyNo());
			wfTypeStatus.setWfType(loan.getWfType());
			wfTypeStatus.setWfDate(new Date());
			wfTypeStatus.setWfStatus(StatusContexts.O2O_FK_OVER);
			int effectRow = wfTypeStatusDao.updateById(wfTypeStatus);
			if (effectRow <= 0) {
				logger.info("ReferId:[{}],更新工作流状态表失败", loan.getLoanapplyNo());
				throw new RuntimeException("ReferId:[{}],更新工作流状态表失败" + loan.getLoanapplyNo());
			}
		}
	}

	/**
	 * 作废-记录到操作日志表
	 * 
	 * @param loanapply
	 * @param loan
	 */
	public void saveLog(O2oLoanapplyEntity loanapply, O2oLoanapplyEntity loan, String reMark) {
		// 对象转json
		ObjectMapper mapper = new ObjectMapper();
		try {
			String userName = "";
			if (StringUtil.isNotBlank(UserHolder.getUser().getCname())) {
				userName = UserHolder.getUser().getCname();
			} else {
				userName = "系统管理员";
			}
			// 记录到操作日志表
			o2oLoanapplyService.saveLog(userName, O2oLogType.LOAN_STATUS_T, mapper.writeValueAsString(loanapply), mapper.writeValueAsString(loan));
			// 记录到【结清操作记录】和【作废操作记录】 日志表
			o2oRecordLogService.saveLog(loan.getBillCode(), userName, O2oLogType.LOAN_STATUS_T, loan.getEndDate(), reMark, "录入");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@Autowired
	O2oZxServiceImpl o2oZxServiceImpl;

	@Override
	public ModelResult<Boolean> creditCancle(O2oCacleEntity payform) {
		ModelResult<Boolean> modelResult = new ModelResult<Boolean>();
		User user = null;
		if (null == UserHolder.getUser()) {
			user = new User();
			user.setNo("1");
			user.setCname("系统管理员");
		} else {
			user = UserHolder.getUser();
		}
		O2oCacleEntity cacleEntity = findByIdEntity(payform.getId());
		O2oZxEntity o2oZxEntity = o2oZxServiceImpl.getEntityById(cacleEntity.getLoanapplyNo());
		if (null == cacleEntity || null == o2oZxEntity) {
			logger.info("cancle workflow fail number:null flow successfully,fail message:cacleEntity is null");
			modelResult.withError("cancle workflow fail", "fail message:cacleEntity is null");
			return modelResult;
		} else if (StatusContexts.O2O_FK_OVER.equals(o2oZxEntity.getIsDel())) {
			logger.info("cancle workflow fail number:{} flow successfully,fail message:creditId is cancled", o2oZxEntity.getId());
			modelResult.withError("cancle workflow fail", "fail message:creditId is cancled");
			return modelResult;
		} else if (StatusContexts.O2O_BANK_CLO.equals(o2oZxEntity.getZxStatus())) {
			logger.info("cancle workflow fail number:{} flow successfully,fail message:creditId workflow is end", o2oZxEntity.getId());
			modelResult.withError("cancle workflow fail", "fail message:creditId workflow is end");
			return modelResult;
		}
		boolean status = StatusContexts.O2O_NEW.equals(o2oZxEntity.getZxStatus());
		if (status) {
			update(o2oZxEntity, cacleEntity);
		} else {
			CancleProcessParam cancleProcessParam = new CancleProcessParam();
			cancleProcessParam.setReferId(cacleEntity.getLoanapplyNo());
			cancleProcessParam.setOperName(user.getCname());
			cancleProcessParam.setOperNo(user.getNo());
			cancleProcessParam.setCancleReason(cacleEntity.gettRemark());
			logger.info("cancle workflow number:{} ", o2oZxEntity.getId());
			cancleProcessParam.setProcessType("PROCESS_ACCESS");
			com.eascs.workflow.common.vo.ModelResult<Boolean> model = workFlowService.cancelProcess(cancleProcessParam);
			if (model.isSuccess()) {
				update(o2oZxEntity, cacleEntity);
			}
			modelResult.withModel(model.getModel());
		}
		return modelResult;
	}

	public void update(O2oZxEntity o2oZxEntity, O2oCacleEntity cacleEntity) {
		logger.info("cancle workflow number:{} message :success", o2oZxEntity.getId());
		o2oZxEntity.setIsDel(StatusContexts.O2O_FK_OVER);
		int i = o2oZxServiceImpl.update(o2oZxEntity);
		if (i > 0) {
			// 更新作废记录表状态
			cacleEntity.settIsSuccess(StatusContexts.O2O_YES);
			updateCalcle(cacleEntity);
			String userName = "";
			if (StringUtil.isNotBlank(UserHolder.getUser().getCname())) {
				userName = UserHolder.getUser().getCname();
			} else {
				userName = "系统管理员";
			}
			// 记录到操作日志表
			o2oLoanapplyService.saveLog(userName, O2oLogType.LOAN_STATUS_T, null, null);
			// 记录到【结清操作记录】和【作废操作记录】 日志表
			o2oRecordLogService.saveLog(o2oZxEntity.getBillCode(), userName, O2oLogType.LOAN_STATUS_T, o2oZxEntity.getEndDate(), cacleEntity.gettRemark(), "录入");
		}
	}

	@Override
	public ModelResult<Boolean> loanNewCancle() {
		ModelResult<Boolean> result = new ModelResult<Boolean>();
		String sql = "SELECT ol.loanapply_no,ol.wf_type FROM o2o_loanapply ol where ol.wf_type='NEW' and ol.loanapply_no" + " not in (SELECT wf.loanapply_no from wf_type_status wf where wf.wf_type = 'ZX') and TO_DAYS(now()) - TO_DAYS(ol.create_date) >= 60";
		List<O2oLoanapplyEntity> list = cancleDao.findEntitys(sql, O2oLoanapplyEntity.class);
		if (!list.isEmpty() && list.size() > 0) {
			O2oCacleEntity cacle = null;
			for (O2oLoanapplyEntity entity : list) {
				cacle = new O2oCacleEntity();
				cacle.setLoanapplyNo(entity.getLoanapplyNo());
				cacle.settOperno("10000");
				cacle.settOpername("为系统自动作废");
				cacle.settTime(new Date());
				cacle.settType(entity.getWfType());
				cacle.settWhy("为贷款申请超时作废");
				cacle.settRemark("为贷款申请超时作废");
				cacle.settIsSuccess("N");
				cacle.settSysType("ST");// 自动作废类型
				int i = cancleDao.insert(cacle);
				if (i > 0) {
					result = worlFlowCancle(cacle);
				} else {
					result.withError("auto cacle fail,reson:[{}]", "insert into o2o_loan_t_info is error");
				}
			}
		}
		result.withModel(true);
		return result;
	}

}
